import logging
import shutil
import zipfile
from pathlib import Path

import rarfile
from tqdm import tqdm


class FileProcessor:
    """
    解压缩
    按文件类型分类保存文件
    """


    def __init__(self, input_dir, output_dir):
        self.logger = None
        self.input_dir = Path(input_dir)
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)
        self.setup_logging()

    def setup_logging(self):
        """配置日志记录"""
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(self.output_dir / 'file_processing.log'),
                logging.StreamHandler()
            ]
        )
        self.logger = logging.getLogger(__name__)

    def extract_archive(self, archive_path, extract_to):
        """解压压缩文件，自动覆盖已存在文件"""
        try:
            if archive_path.suffix.lower() == '.zip':
                with zipfile.ZipFile(archive_path, 'r') as zip_ref:
                    # extractall 默认会覆盖已存在的文件[5,7](@ref)
                    zip_ref.extractall(extract_to)
                self.logger.info(f"解压ZIP文件: {archive_path} -> {extract_to}")

            elif archive_path.suffix.lower() == '.rar':
                with rarfile.RarFile(archive_path, 'r') as rar_ref:
                    # extractall 默认会覆盖已存在的文件
                    rar_ref.extractall(extract_to)
                self.logger.info(f"解压RAR文件: {archive_path} -> {extract_to}")

        except Exception as e:
            self.logger.error(f"解压失败 {archive_path}: {str(e)}")

    def categorize_file(self, file_path, category):
        """将文件分类到指定目录，自动覆盖已存在文件"""
        try:
            category_dir = self.output_dir / category
            category_dir.mkdir(exist_ok=True, parents=True)

            dest_path = category_dir / file_path.name

            # 直接覆盖已存在的文件[2](@ref)
            shutil.copy2(file_path, dest_path)
            self.logger.info(f"分类文件: {file_path} -> {dest_path}")

        except Exception as e:
            self.logger.error(f"文件分类失败 {file_path}: {str(e)}")

    def process_directory(self, current_dir):
        """递归处理目录"""
        self.logger.info(f"开始处理目录: {current_dir}")

        # 首先处理压缩文件
        archives = list(current_dir.glob('*.zip')) + list(current_dir.glob('*.rar'))
        for archive in tqdm(archives, desc="解压文件中"):
            extract_dir = current_dir / f"extracted_{archive.stem}"
            extract_dir.mkdir(exist_ok=True)
            self.extract_archive(archive, extract_dir)

        # 处理所有文件（包括解压出来的文件）
        all_files = list(current_dir.glob('*.*'))

        # 去重并排除压缩文件
        unique_files = set(all_files)
        files_to_process = [f for f in unique_files if f.is_file() and f.suffix.lower() not in ['.zip', '.rar']]

        for file_path in tqdm(files_to_process, desc="分类文件中"):
            ext = file_path.suffix.lower()
            deal_exts = ['.ape', '.flac', '.m4a', '.mp3', '.wav']
            if ext in deal_exts:
                category = ext.replace('.', '')
                self.categorize_file(file_path, category)
            else:
                self.categorize_file(file_path, '其他')

        # 递归处理子目录
        subdirs = [d for d in current_dir.iterdir() if d.is_dir() and not d.name.startswith('extracted_')]
        for subdir in tqdm(subdirs, desc="处理子目录中"):
            self.process_directory(subdir)

    def run(self):
        """运行处理流程"""
        self.logger.info(f"开始处理，输入目录: {self.input_dir}, 输出目录: {self.output_dir}")

        if not self.input_dir.exists():
            self.logger.error(f"输入目录不存在: {self.input_dir}")
            return

        self.output_dir.mkdir(exist_ok=True, parents=True)

        try:
            self.process_directory(self.input_dir)
            self.logger.info("处理完成！")
        except Exception as e:
            self.logger.error(f"处理过程中发生错误: {str(e)}")
            raise